import os
import functools
import time

def ensure_containing_dir_exists(file_path):
    dir_path = os.path.dirname(file_path)
    if not os.path.isdir(dir_path):
        os.makedirs(dir_path, 0700)

def globally_locked(lock):
    """Returns a decorator that ensures the function acquires the given lock
    whenever it is called and releases it when it returns.
    """
    def decorator(function):
        @functools.wraps(function)
        def wrapper(*args, **kwargs):
            with lock:
                return function(*args, **kwargs)
        return wrapper
    return decorator

def join_with_slashes(first_part, *other_parts):
    """This function is like os.path.join, except it *always* uses slashes
    ('/'), regardless of the value of os.path.sep.
    """
    path = first_part
    for other_part in other_parts:
        if other_part.startswith("/"):
            path = other_part
        elif len(path) == 0 or path.endswith("/"):
            path += other_part
        else:
            path += "/" + other_part

    return path

def extension(file_name):
    """Using this convenience function is shorter than type os.path.splitext."""
    return os.path.splitext(file_name)[1]

def unique(sequence):
    """Return a list of items, preserving the order of the elements in the
    given sequence but removing duplicate ones.
    """
    result = []
    encountered_elements = set()
    for element in sequence:
        if element not in encountered_elements:
            result.append(element)
            encountered_elements.add(element)

    return result

class DictWithAttrs(dict):
    """This dictionary exposes its keys as object attributes."""
    def __init__(self, *args, **kwargs):
        super(DictWithAttrs, self).__init__(*args, **kwargs)
        self.__dict__ = self

    def __setattribute__(self, name, value):
        self[name] = value

def decorate_if(condition, decorator):
    return lambda function: (decorator(function) if condition else function)

def timed(function):
    @functools.wraps(function)
    def wrapper(*args, **kwargs):
        start_time = time.time()
        try:
            return function(*args, **kwargs)
        finally:
            end_time = time.time()
            print function.__name__, end_time - start_time

    return wrapper

def timed_accumulated(function):
    @functools.wraps(function)
    def wrapper(*args, **kwargs):
        start_time = time.time()
        try:
            return function(*args, **kwargs)
        finally:
            wrapper.total_time += time.time() - start_time

    wrapper.total_time = 0.0
    return wrapper
